package ai.turbochain.ipex.job;

import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import ai.turbochain.ipex.entity.ExchangeTrade;
import ai.turbochain.ipex.entity.KLine;
import ai.turbochain.ipex.processor.CoinProcessorFactory;
import ai.turbochain.ipex.service.MarketService;
import ai.turbochain.ipex.util.DateUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 生成各时间段的K线信息
 *
 */
@Component
@Slf4j
public class KLineGeneratorJob {
    @Autowired
    private CoinProcessorFactory processorFactory;
    public static final String Period_1hour =  "1hour";
    public static final String Period_1day = "1day";
    public static final String Period_1week = "1week";
    public static final String Period_1month = "1month";
    @Autowired
    private MarketService marketService;
    @Autowired
    private RedisTemplate redisTemplate;
    
    /**
     * 每分钟定时器，处理分钟K线
     */
    @Scheduled(cron = "0 * * * * *")
    public void handle5minKLine(){
        Calendar calendar = Calendar.getInstance();
        log.debug("分钟K线:{}",calendar.getTime());
        //将秒、微秒字段置为0
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        long time = calendar.getTimeInMillis();
        int minute = calendar.get(Calendar.MINUTE);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        processorFactory.getProcessorMap().forEach((symbol,processor)->{
            log.debug("生成{}分钟k线:{}",symbol);
            //生成1分钟K线
            processor.autoGenerate();
            //更新24H成交量
            processor.update24HVolume(time);
            if(minute%5 == 0) {
                processor.generateKLine(5, Calendar.MINUTE, time);
            }
            if(minute%10 == 0){
                processor.generateKLine(10, Calendar.MINUTE,time);
            }
            if(minute%15 == 0){
                processor.generateKLine(15, Calendar.MINUTE,time);
            }
            if(minute%30 == 0){
                processor.generateKLine(30, Calendar.MINUTE,time);
            }
            if(hour == 0 && minute == 0){
                processor.resetThumb();
            }
        });
    }

    /**
     * 每小时运行 时K线
     */
    @Scheduled(cron = "0 1 * * * *")
    public void handleHourKLine(){
        processorFactory.getProcessorMap().forEach((symbol,processor)-> {
            Calendar calendar = Calendar.getInstance();
            log.info("小时K线:{}",calendar.getTime());
            //将秒、微秒字段置为0
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            long time = calendar.getTimeInMillis();

            processor.generateKLine(1, Calendar.HOUR_OF_DAY, time);
        });
    }
    
   
    /**
         * 每日0点5分统计昨天交易-日K线
     */
    @Scheduled(cron = "0 5 0 * * *")
    public void handleDayKLine2() {
    	final long startTick = DateUtil.getYestDayBeginTime();
    	final long endTick =  DateUtil.getTodayBeginTime();
    	System.out.println("=====按日统计报表程序启动======"+startTick);
    	
    	// TODO 需要修改
    	processorFactory.getProcessorMap().forEach((symbol,processor)->{
             processor.generateKLine2(startTick, endTick,Period_1day);
        });
    	
    	System.out.println("=====按日统计报表程序结束======"+endTick);
    }
    
    
    /**
         * 每周一统计上周的交易数据
     * 
     */
    @Scheduled(cron = "0 10 0 ? * MON") 
    public void handleWeekKLine() {//每周一上午0:10触发 
    	System.out.println("=====按周统计报表程序启动======");
    	
    	final long startTick = DateUtil.getBeforeFirstWeekDate();
    	final long endTick =  DateUtil.getBeginDayOfWeek();
    	
		System.out.println(startTick + "========" + endTick);
    	
    	// TODO 需要修改
    	processorFactory.getProcessorMap().forEach((symbol,processor)->{
             processor.generateKLine2(startTick, endTick,Period_1week);
        });
    	
    	System.out.println("=====按周统计报表程序结束======");
    }
    
    
    /**
       * 每月一号统计上月的交易数据
     *  
     */
    @Scheduled(cron = "0 15 0 1 * ?")  
    public void handleMonthKLine() {//每月1日上午0:15触发
    	System.out.println("=====按月统计报表程序启动======");
    	
    	final long startTick = DateUtil.getBeforeFirstMonthDate();
    	final long endTick =  DateUtil.getFirstDateOfMonth();
		 
		System.out.println(startTick + "========" + endTick);
    	
    	// TODO 需要修改
    	processorFactory.getProcessorMap().forEach((symbol,processor)->{
             processor.generateKLine2(startTick, endTick,Period_1month);
        });
    	 
    	System.out.println("=====按月统计报表程序结束======");
    }
    
    
    
    
    /**
     * 每15分，30分，45分时触发任务
       * 统计当天交易数据
     */
    @Scheduled(cron = "0 15,30,45 * * * *")
    public void handleTodayKLine(){
        processorFactory.getProcessorMap().forEach((symbol,processor)-> {
            
            Calendar calendar = Calendar.getInstance();
            long start = DateUtil.getTodayBeginTime();
            // 按小时统计累计入当天
            List<ExchangeTrade> exchangeTrades = marketService.findTradeByTimeRange(symbol, start, calendar.getTimeInMillis());

            KLine kLine = new KLine();
            kLine.setTime(start);
            
            // 处理K线信息
            for (ExchangeTrade exchangeTrade : exchangeTrades) {
            	processor.processTrade(kLine, exchangeTrade);
            }
            String key = start+symbol+Period_1day;
            ValueOperations valueOperations = redisTemplate.opsForValue();
            valueOperations.set(key, kLine, 1, TimeUnit.DAYS);
        });
    }
    
    /**
     * 每日凌晨2点5分统计当前周数据
     */
    @Scheduled(cron = "0 5 2 * * *")
    public void handleThisWeekKLine() {
    	// 累计当前周数据
    	 processorFactory.getProcessorMap().forEach((symbol,processor)-> {
             
             Calendar calendar = Calendar.getInstance();
             long start = DateUtil.getBeginDayOfWeek();
             
             List<ExchangeTrade> exchangeTrades = marketService.findTradeByTimeRange(symbol, start, calendar.getTimeInMillis());

             KLine kLine = new KLine();
             kLine.setTime(start);
             
             // 处理K线信息
             for (ExchangeTrade exchangeTrade : exchangeTrades) {
             	processor.processTrade(kLine, exchangeTrade);
             }
             String key = start+symbol+Period_1week;
             ValueOperations valueOperations = redisTemplate.opsForValue();
             valueOperations.set(key, kLine, 7, TimeUnit.DAYS);
    	 });
    }
    
    
    /**
     * 每日凌晨3点15分统计当月数据
     */
    @Scheduled(cron = "0 15 3 * * *")
    public void handleThisMonthKLine() {
    	// 累计当月数据
    	 processorFactory.getProcessorMap().forEach((symbol,processor)-> {
             
             Calendar calendar = Calendar.getInstance();
             long from = DateUtil.getFirstDateOfMonth();
             long to = calendar.getTimeInMillis();
             
             KLine kLine = new KLine();
             kLine.setTime(from);
             
             List<KLine> list = marketService.findAllKLine(symbol,from,to,"1day");
             
             // 处理K线信息
             for (KLine newKline : list) {
             	processor.processTrade(kLine, newKline);
             }
             String key = from+symbol+Period_1month;
             ValueOperations valueOperations = redisTemplate.opsForValue();
             valueOperations.set(key, kLine, 31, TimeUnit.DAYS);
    	 });
    }
}
